package com.loveprogrammer.bytebuddy;

import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.implementation.FixedValue;
import net.bytebuddy.implementation.MethodDelegation;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;

/**
 * @ClassName ApiTest
 * @Description TODO
 * @Author admin
 * @Date 2023/11/20 15:40
 * @Version 1.0
 */
public class ApiTest {

    public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {

//        DynamicType.Unloaded<?> dynamicType = new ByteBuddy()
//                .subclass(Object.class)
//                .name("com.loveprogrammer.bytebuddy.HelloWorld")
//                .make();
//
//        outputClazz(dynamicType.getBytes());

//        DynamicType.Unloaded<?> dynamicType = new ByteBuddy()
//                .subclass(Object.class)
//                .name("com.loveprogrammer.bytebuddy.HelloWorld")
//                .defineMethod("main",void.class, Modifier.PUBLIC + Modifier.STATIC)
//                .withParameter(String[].class,"args")
//                .intercept(FixedValue.value("Hello World!"))
//                .make();
//
//        outputClazz(dynamicType.getBytes());

        DynamicType.Unloaded<?> dynamicType = new ByteBuddy()
                .subclass(Object.class)
                .name("com.loveprogrammer.bytebuddy.HelloWorld")
                .defineMethod("main", void.class, Modifier.PUBLIC + Modifier.STATIC)
                .withParameter(String[].class, "args")
                .intercept(MethodDelegation.to(Hi.class))
                .make();

        outputClazz(dynamicType.getBytes());

        Class<?> clazz = dynamicType.load(ApiTest.class.getClassLoader()).getLoaded();

        // 反射调用
        clazz.getMethod("main",String[].class).invoke(clazz.newInstance(),(Object) new String[1]);
    }


    private static void outputClazz(byte[] bytes) {
        FileOutputStream out = null;
        try {
            String pathName = ApiTest.class.getResource("/").getPath() + "ByteBuddyHelloWorld.class";
            out = new FileOutputStream(new File(pathName));
            System.out.println("类输出路径：" + pathName);
            out.write(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != out) try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}
